
function buildShader(vs, fs) {
    let gl = globalThis.app.gl;
    let vsShader = createShader(gl.VERTEX_SHADER, vs);
    let fsShader = createShader(gl.FRAGMENT_SHADER, fs);
    let program = gl.createProgram();
    gl.attachShader(program, vsShader);
    gl.attachShader(program, fsShader);
    gl.linkProgram(program);

    let msg = gl.getProgramInfoLog(program);
    if (msg.length > 0) {
        throw msg;
    }

    gl.detachShader(program, vsShader);
    gl.detachShader(program, fsShader);

    return {
        vs: vsShader,
        fs: fsShader,
        program: program,
        uniforms: {},
        attribs: {},
    };
}

function createUniforms(shaderInfo, uniformNames) {
    let gl = globalThis.app.gl;
    uniformNames.forEach(name => {
        let location = gl.getUniformLocation(shaderInfo.program, name);
        if (!location) {
            throw `getUniformLocation for ${name} failed!`;
        }
        shaderInfo.uniforms[name] = location;
    });
}

function createAttribs(shaderInfo, attribs) {
    let gl = globalThis.app.gl;
    attribs.forEach(name => {
        let location = gl.getAttribLocation(shaderInfo.program, name);
        if (location < 0) {
            throw `getAttribLocation for ${name} failed!`;
        }
        shaderInfo.attribs[name] = location;
    });
}

function createShader(shaderType, source) {
    let gl = globalThis.app.gl;
    let shader = gl.createShader(shaderType);
    if (shader <= 0) {
        throw `create shaderType:${shaderType} error!`;
    }
    gl.shaderSource(shader, source);
    gl.compileShader(shader);

    let msg = gl.getShaderInfoLog(shader);
    if (msg.length > 0) {
        throw msg;
    }
    return shader;
}

module.exports = {
    buildShader:buildShader,
    createUniforms:createUniforms,
    createAttribs:createAttribs,
};
